package com.zxw.gateway.exception;

import com.zxw.common.api.ApiResult;
import com.zxw.common.enums.ResultCode;
import com.zxw.common.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 统一异常处理
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理校验异常
     *
     * @param exception 校验异常对象MethodArgumentNotValidException
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public ApiResult handlerValidException(MethodArgumentNotValidException exception) {
        Map<String, String> map = new HashMap<>();
        BindingResult result = exception.getBindingResult();
        result.getFieldErrors().forEach((item) -> {
            String message = item.getDefaultMessage();
            //只取|后的字符
            String[] messageSplit = message.split("\\|");
            if (messageSplit.length > 1) {
                message = messageSplit[1];
            }

            String field = item.getField();
            map.put(field, message);
        });
        return ApiResult.failed(ResultCode.INVALID_ERROR, map);
    }

    /**
     * 处理自定义CustomException异常
     *
     * @param exception 自定义异常对象CustomException
     * @return 返回错误响应对象
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(BizException.class)
    public ApiResult handleRRException(BizException exception) {
        return ApiResult.failed(exception.getCode(), exception.getMessage());
    }

    /**
     * 处理文件上传大小错误异常
     *
     * @param exception 异常对象MultipartException
     * @return 返回错误响应对象
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = MultipartException.class)
    public ApiResult handleSizeLimitExceededException(MultipartException exception) {
        return ApiResult.failed(ResultCode.FILE_SIZE_TOO_BIG_ERROR);
    }


    /**
     * 参数类型异常
     *
     * @param exception
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ApiResult handleHttpMessageNotReadableException(HttpMessageNotReadableException exception) {
        return ApiResult.failed(ResultCode.PARAMETER_TYPE_ERROR);
    }


    /**
     * 其他异常
     *
     * @param exception 其他异常对象
     * @return
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = Exception.class)
    public ApiResult handleException(Exception exception) {
        log.info(exception.toString());
        return ApiResult.failed(ResultCode.OTHER_ERROR.getCode(), exception.getMessage());
    }


    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = {ConstraintViolationException.class})
    public ApiResult handlerConstraintViolationException(ConstraintViolationException exception) {
        Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();
        Map<String, String> map = new HashMap<>();
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            String message = constraintViolation.getMessage();
            //只取|后的字符
            String[] messageSplit = message.split("\\|");
            if (messageSplit.length > 1) {
                message = messageSplit[1];
            }
            String field = constraintViolation.getPropertyPath().toString();
            int fieldFilterIndex = field.indexOf(".");
            map.put(field.substring(fieldFilterIndex > -1 ? fieldFilterIndex + 1 : 0), message);
        }
        return ApiResult.failed(ResultCode.INVALID_ERROR, map);
    }
}
